package com.ds.infrastructure.audit.client.track;

import com.alibaba.fastjson.JSON;
import com.ds.infrastructure.audit.client.constant.KbaClientConstant;
import com.ds.infrastructure.audit.common.constant.CommonConstant;
import com.ds.infrastructure.audit.common.entity.KbaBehaviorWrapper;
import com.ds.infrastructure.audit.common.exception.KbaAuditException;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.kafka.clients.producer.KafkaProducer;
import org.apache.kafka.clients.producer.ProducerRecord;
import org.apache.kafka.clients.producer.RecordMetadata;

import java.util.Properties;
import java.util.concurrent.Future;

/**
 * 作用： 考虑支持Java原生项目
 *
 * @author WeiShaoying
 * @date 2020/7/27
 */
@Slf4j
@SuppressWarnings("all")
public class KbaProtocolTrackMq extends AbstractKbaTrack {

    public KbaProtocolTrackMq(String server) {
        super(server);
    }

    public KbaProtocolTrackMq(String server, String appName, String appKey) {
        super(server, appName, appKey);
    }

    private static KafkaProducer<String, String> kafkaProducer;

    private static Properties props = new Properties();


    static {
        // 等待所有副本节点的应答
        props.put("acks", "all");
        // 消息发送最大尝试次数
        props.put("retries", 3);
        // 一批消息处理大小16KB
        props.put("batch.size", 16384);
        // 请求延时
        props.put("linger.ms", 100);
        // 发送缓存区内存大小 32M
        props.put("buffer.memory", 33554432);
        // key序列化
        props.put("key.serializer", "org.apache.kafka.common.serialization.StringSerializer");
        // value序列化
        props.put("value.serializer", "org.apache.kafka.common.serialization.StringSerializer");
        //自定义序列化
        //props.put("value.serializer", KbaBehaviorWrapperEncoder.class.getName());
    }

    /**
     * 初始化
     */
    @Override
    public void initialize() {
        // Kafka服务器主机名和端口号
        if (StringUtils.isBlank(server)) {
            this.server = KbaClientConstant.DEFT_MQ_BROKER;
        }
        props.put("bootstrap.servers", this.server);
        kafkaProducer = new KafkaProducer<>(props);
    }

    /**
     * Kba上报
     *
     * @param behavior
     * @throws KbaAuditException
     */
    @Override
    public void report0(KbaBehaviorWrapper wrapper) throws KbaAuditException {
        try {
            kafkaProducer.send(new ProducerRecord(CommonConstant.TOPIC_MSG_COLLECTOR, JSON.toJSONString(wrapper)));
            kafkaProducer.flush();
        } catch (Exception e) {
            log.error(e.getMessage(), e);
            throw new KbaAuditException(e.getMessage(), e);
        }
    }


    /**
     * 上报并指定回调处理
     *
     * @param behavior
     * @param callback
     * @throws KbaAuditException
     */
    @Override
    public void report0(KbaBehaviorWrapper wrapper, KbaCallback callback) throws KbaAuditException {
        try {
            callback.preProcess();
            Future<RecordMetadata> future = kafkaProducer.send(new ProducerRecord(CommonConstant.TOPIC_MSG_COLLECTOR, JSON.toJSONString(wrapper)));
            kafkaProducer.flush();
            callback.onSuccess(future);
        } catch (Exception e) {
            log.error(e.getMessage(), e);
            callback.onError(e);
            throw new KbaAuditException(e.getMessage(), e);
        }
    }

}
